package com.bdd.crowd.mvc.config;

import com.bdd.crowd.constant.CrowdConstant;
import com.bdd.crowd.exception.LoginAcctAlreadyInUseException;
import com.bdd.crowd.exception.LoginAcctAlreadyInUseFroeUpdateException;
import com.bdd.crowd.exception.LoginFailedException;
import com.bdd.crowd.utils.CrowdUtil;
import com.bdd.crowd.utils.ResultEntity;
import com.google.gson.Gson;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author banddong
 * @create 2020-08-22 8:54
 *
 * 基于注解的异常映射
 * @ControllerAdvice:声明这是一个异常处理类
 */
@ControllerAdvice
public class CrowdExceptionResolver {


    /**
     * 添加用户名存在时
     * @param exception
     * @param request
     * @param response
     * @return 添加页面
     * @throws IOException
     */

    @ExceptionHandler(value = LoginAcctAlreadyInUseFroeUpdateException.class)
    public ModelAndView loginAcctAlreadyInUseFroeUpdateException(
            LoginAcctAlreadyInUseFroeUpdateException exception,
            HttpServletRequest request,
            HttpServletResponse response) throws IOException {

        String viewName = "system-error";

        return commonResolver(viewName,exception,request,response);
    }
    /**
     * 添加用户名存在时
     * @param exception
     * @param request
     * @param response
     * @return 添加页面
     * @throws IOException
     */

    @ExceptionHandler(value = LoginAcctAlreadyInUseException.class)
    public ModelAndView resolverLoginAcctAlreadyInUseException(
            LoginAcctAlreadyInUseException exception,
            HttpServletRequest request,
            HttpServletResponse response) throws IOException {

        String viewName = "admin-add";

        return commonResolver(viewName,exception,request,response);
    }

    /**
     * 登录时异常处理
     * @param exception
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = LoginFailedException.class)
    public ModelAndView resolverLoginFailedException(
            LoginFailedException exception,
            HttpServletRequest request,
            HttpServletResponse response) throws IOException {

        String viewName = "admin-login";

        return commonResolver(viewName,exception,request,response);
    }

    /**
     * 空指针异常
     * @param exception
     * @param request
     * @param response
     * @return
     * @throws IOException
     * @ExceptionHandler：将异常类型和方法绑定起来
     */
    @ExceptionHandler(value = NullPointerException.class)
    public ModelAndView resolverNullPointerException(
            NullPointerException exception,
            HttpServletRequest request,
            HttpServletResponse response) throws IOException {

        String viewName = "system-error";

        return commonResolver(viewName,exception,request,response);
    }

    /**
     * 数字异常
     * @param exception
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = ArithmeticException.class)
    public ModelAndView resolverMathException(
            ArithmeticException exception,
            HttpServletRequest request,
            HttpServletResponse response) throws IOException {

        String viewName = "system-error";

        return commonResolver(viewName,exception,request,response);
    }


    /**
     *
     * @param viewName
     * @param exception
     * @param request
     * @param response
     * @return
     * @throws IOException
     * 重复代码抽取成方法
     */
    private ModelAndView commonResolver(
        //异常处理完成要去的页面
        String viewName,
        //实际捕获的异常
        Exception exception,
        //当前的请求对象
        HttpServletRequest request,
        //当前的响应对象
        HttpServletResponse response) throws IOException {
        // 1.判断当前请求类型
        boolean judgeRequestType = CrowdUtil.judgeRequestType(request);
        // 2.如果是Ajax请求
        if(judgeRequestType){
            // 3.创建ResultEntity对象
            ResultEntity<Object> failed = ResultEntity.failed(exception.getMessage());
            // 4.创建gson对象
            Gson gson = new Gson();
            // 5.将ResultEntity对象转为JSON对象
            String json = gson.toJson(failed);
            // 6.将JSON字符串作为响应体返给浏览器
            response.getWriter().write(json);
            // 7.由于上面已经通过了原生的response对象，所以不提供ModelAndView对象
            return null;
        }
        // 8.如果不是Ajax请求则创建ModelAndView视图
        ModelAndView modelAndView = new ModelAndView();
        // 9.将Execption对象存入模型
        modelAndView.addObject(CrowdConstant.ATTR_NAME_EXCEPTION,exception);
        // 10.设置对应的视图名称
        modelAndView.setViewName(viewName);
        // 11.返回ModelAndView对象
        return modelAndView;
    }


}
